home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 051-075 / scopedisk75 / ispell / src / buildhash.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  6KB  |  327 lines

  1. /* -*- Mode: Text -*- */
  2. /*
  3.  * buildhash.c - make a hash table for ispell
  4.  *
  5.  * Pace Willisson, 1983
  6.  */
  7.  
  8. #include <stdio.h>
  9. #ifndef AMIGA        /* i am not sure why this is here */
  10. #include <sys/types.h>
  11. #endif
  12. #include <stat.h>
  13. #include "ispell.h"
  14.  
  15. #define DICT "dict.191"
  16. #define COUNT "count.191"
  17. #define STATS "stats.191"
  18.  
  19. #define NSTAT 100
  20. struct stat dstat, cstat;
  21.  
  22. int numwords, hashsize;
  23.  
  24. char *malloc();
  25.  
  26. struct dent *hashtbl;
  27.  
  28. main ()
  29. {
  30.     FILE *countf;
  31.     FILE *statf;
  32.     int stats[NSTAT];
  33.     int i;
  34.  
  35.     if (stat (DICT, &dstat) < 0) {
  36.         fprintf (stderr, "No dictionary (%s)\n", DICT);
  37.         exit (1);
  38.     }
  39.  
  40.     if (stat (COUNT, &cstat) < 0 || dstat.st_mtime > cstat.st_mtime)
  41.         newcount ();
  42.  
  43.     if ((countf = fopen (COUNT, "r")) == NULL) {
  44.         fprintf (stderr, "No count file\n");
  45.         exit (1);
  46.     }
  47.     numwords = 0;
  48.     fscanf (countf, "%d", &numwords);
  49.     fclose (countf);
  50.     if (numwords == 0) {
  51.         fprintf (stderr, "Bad count file\n");
  52.         exit (1);
  53.     }
  54.     hashsize = numwords;
  55.     readdict ();
  56.  
  57.     if ((statf = fopen (STATS, "w")) == NULL) {
  58.         fprintf (stderr, "Can't create %s\n", STATS);
  59.         exit (1);
  60.     }
  61.  
  62.     for (i = 0; i < NSTAT; i++)
  63.         stats[i] = 0;
  64.     for (i = 0; i < hashsize; i++) {
  65.         struct dent *dp;
  66.         int j;
  67.         if (hashtbl[i].used == 0) {
  68.             stats[0]++;
  69.         } else {
  70.             for (j = 1, dp = &hashtbl[i]; dp->next != NULL; j++, dp = dp->next)
  71.                 ;
  72.             if (j >= NSTAT)
  73.                 j = NSTAT - 1;
  74.             stats[j]++;
  75.         }
  76.     }
  77.     for (i = 0; i < NSTAT; i++)
  78.         fprintf (statf, "%d: %d\n", i, stats[i]);
  79.     fclose (statf);
  80.  
  81.     filltable ();
  82.  
  83.     output ();
  84. }
  85.  
  86. output ()
  87. {
  88.     FILE *outfile;
  89.     struct hashheader hashheader;
  90.     int strptr, n, i;
  91.  
  92.     if ((outfile = fopen ("ispell.hash", "w")) == NULL) {
  93.         fprintf (stderr, "can't create ispell.hash\n");
  94.         return;
  95.     }
  96.     hashheader.magic = MAGIC;
  97.     hashheader.stringsize = 0;
  98.     hashheader.tblsize = hashsize;
  99.     fwrite (&hashheader, sizeof hashheader, 1, outfile);
  100.     strptr = 0;
  101.     for (i = 0; i < hashsize; i++) {
  102.         n = strlen (hashtbl[i].word) + 1;
  103.         fwrite (hashtbl[i].word, n, 1, outfile);
  104.         hashtbl[i].word = (char *)strptr;
  105.         strptr += n;
  106.     }
  107.     for (i = 0; i < hashsize; i++) {
  108.         if (hashtbl[i].next != 0) {
  109.             int x;
  110.             x = hashtbl[i].next - hashtbl;
  111.             hashtbl[i].next = (struct dent *)x;
  112.         } else {
  113.             hashtbl[i].next = (struct dent *)-1;
  114.         }
  115.     }
  116.     fwrite (hashtbl, sizeof (struct dent), hashsize, outfile);
  117.     hashheader.stringsize = strptr;
  118.     rewind (outfile);
  119.     fwrite (&hashheader, sizeof hashheader, 1, outfile);
  120.     fclose (outfile);
  121. }
  122.  
  123. filltable ()
  124. {
  125.     struct dent *freepointer, *nextword, *dp;
  126.     int i;
  127.  
  128.     for (freepointer = hashtbl; freepointer->used; freepointer++)
  129.         ;
  130.     for (nextword = hashtbl, i = numwords; i != 0; nextword++, i--) {
  131.         if (nextword->used == 0) {
  132.             continue;
  133.         }
  134.         if (nextword->next == NULL) {
  135.             continue;
  136.         }
  137.         if (nextword->next >= hashtbl && nextword->next < hashtbl + hashsize) {
  138.             continue;
  139.         }
  140.         dp = nextword;
  141.         while (dp->next) {
  142.             if (freepointer > hashtbl + hashsize) {
  143.                 fprintf (stderr, "table overflow\n");
  144.                 getchar ();
  145.                 break;
  146.             }
  147.             *freepointer = *(dp->next);
  148.             dp->next = freepointer;
  149.             dp = freepointer;
  150.  
  151.             while (freepointer->used)
  152.                 freepointer++;
  153.         }
  154.     }
  155. }
  156.  
  157.  
  158. readdict ()
  159. {
  160.     struct dent d;
  161.     char lbuf[100];
  162.     FILE *dictf;
  163.     int i;
  164.     int h;
  165.     char *p;
  166.  
  167.     if ((dictf = fopen (DICT, "r")) == NULL) {
  168.         fprintf (stderr, "Can't open dictionary\n");
  169.         exit (1);
  170.     }
  171.  
  172.     hashtbl = (struct dent *) calloc (numwords, sizeof (struct dent));
  173.     if (hashtbl == NULL) {
  174.         fprintf (stderr, "couldn't allocate hash table\n");
  175.         exit (1);
  176.     }
  177.  
  178.     i = 0;
  179.     while (fgets (lbuf, sizeof lbuf, dictf) != NULL) {
  180.         if (i % 1000 == 0) {
  181.             printf ("%d ", i);
  182.             fflush (stdout);
  183.         }
  184.         i++;
  185.  
  186.         p = &lbuf [ strlen (lbuf) - 1 ];
  187.         if (*p == '\n')
  188.             *p = 0;
  189.  
  190.         if (makedent (lbuf, &d) < 0)
  191.             continue;
  192.  
  193.         d.word = malloc (strlen (lbuf) + 1);
  194.         if (d.word == NULL) {
  195.             fprintf (stderr, "couldn't allocate space for word %s\n", lbuf);
  196.             exit (1);
  197.         }
  198.         strcpy (d.word, lbuf);
  199.  
  200.         h = hash (lbuf, strlen (lbuf), hashsize);
  201.  
  202.         if (hashtbl[h].used == 0) {
  203.             hashtbl[h] = d;
  204.  
  205.         } else {
  206.             struct dent *dp;
  207.  
  208.             dp = (struct dent *) malloc (sizeof (struct dent));
  209.             if (dp == NULL) {
  210.                 fprintf (stderr, "couldn't allocate space for collision\n");
  211.                 exit (1);
  212.             }
  213.             *dp = d;
  214.             dp->next = hashtbl[h].next;
  215.             hashtbl[h].next = dp;
  216.         }
  217.     }
  218.     printf ("\n");
  219. }
  220.  
  221. /*
  222.  * fill in the flags in d, and put a null after the word in s
  223.  */
  224.  
  225. makedent (lbuf, d)
  226. char *lbuf;
  227. struct dent *d;
  228. {
  229.     char *p, *index();
  230.  
  231.     d->next = NULL;
  232.     d->used = 1;
  233.     d->v_flag = 0;
  234.     d->n_flag = 0;
  235.     d->x_flag = 0;
  236.     d->h_flag = 0;
  237.     d->y_flag = 0;
  238.     d->g_flag = 0;
  239.     d->j_flag = 0;
  240.     d->d_flag = 0;
  241.     d->t_flag = 0;
  242.     d->r_flag = 0;
  243.     d->z_flag = 0;
  244.     d->s_flag = 0;
  245.     d->p_flag = 0;
  246.     d->m_flag = 0;
  247.  
  248.     p = index (lbuf, '/');
  249.     if (p != NULL)
  250.         *p = 0;
  251.     if (strlen (lbuf) > WORDLEN - 1) {
  252.         printf ("%s: word too big\n");
  253.         return (-1);
  254.     }
  255.  
  256.     if (p == NULL)
  257.         return (0);
  258.  
  259.     p++;
  260.     while (*p != NULL) {
  261.         switch (*p) {
  262.         case 'V': d->v_flag = 1; break;
  263.         case 'N': d->n_flag = 1; break;
  264.         case 'X': d->x_flag = 1; break;
  265.         case 'H': d->h_flag = 1; break;
  266.         case 'Y': d->y_flag = 1; break;
  267.         case 'G': d->g_flag = 1; break;
  268.         case 'J': d->j_flag = 1; break;
  269.         case 'D': d->d_flag = 1; break;
  270.         case 'T': d->t_flag = 1; break;
  271.         case 'R': d->r_flag = 1; break;
  272.         case 'Z': d->z_flag = 1; break;
  273.         case 'S': d->s_flag = 1; break;
  274.         case 'P': d->p_flag = 1; break;
  275.         case 'M': d->m_flag = 1; break;
  276.         case 0:
  277.              fprintf (stderr, "no key word %s\n", lbuf);
  278.             continue;
  279.         default:
  280.             fprintf (stderr, "unknown flag %c word %s\n", 
  281.                     *p, lbuf);
  282.             break;
  283.         }
  284.         p++;
  285.         if (*p != '/' && *p != NULL && *p != '\n') {
  286.             fprintf (stderr, "bad format %s (%c 0%o)\n", 
  287.                     lbuf, *p, *p);
  288.             break;
  289.         }
  290.         if (*p)
  291.             p++;
  292.     
  293.     }
  294.     return (0);
  295. }
  296.  
  297. newcount ()
  298. {
  299.     char buf[200];
  300.     FILE *d;
  301.     int i;
  302.  
  303.     fprintf (stderr, "Counting words in dictionary ...\n");
  304.  
  305.     if ((d = fopen (DICT, "r")) == NULL) {
  306.         fprintf (stderr, "Can't open dictionary\n");
  307.         exit (1);
  308.     }
  309.  
  310.     i = 0;
  311.     while (fgets (buf, sizeof buf, d) != NULL) {
  312.         i++;
  313.         if (i % 1000 == 0) {
  314.             printf ("%d ", i);
  315.             fflush (stdout);
  316.         }
  317.     }
  318.     fclose (d);
  319.     printf ("\n%d words\n", i);
  320.     if ((d = fopen (COUNT, "w")) == NULL) {
  321.         fprintf (stderr, "can't create %s\n", COUNT);
  322.         exit (1);
  323.     }
  324.     fprintf (d, "%d\n", i);
  325.     fclose (d);
  326. }
  327.